﻿define([
    'Wjs/ui/widgets/foundation/ViewHashContainer',
    'Wjs/ui/widgets/foundation/ViewSingleContainer',
    'Wjs/ui/widgets/fields/Button',
    'Wjs/ui/elements/mixins/Activatable'
],
function () {
    'use strict';

    var ViewHashContainer = Wjs.getType('ViewHashContainer'),
        ViewSingleContainer = Wjs.getType('ViewSingleContainer'),
        Button = Wjs.getType('Button'),
        getWizard;

    return Wjs.defineOnce({

        type: 'Wizard',

        internal: {

            base: ViewHashContainer,

            mixins: [
                Wjs.getType('Activatable')
            ],

            onBeforeTypeDefined: function () {

                getWizard = function (item) {

                    if (!item.wizard) {

                        item.wizard = item.up(function (p) {

                            return p instanceof Wjs.getType('Wizard');
                        });
                    }

                    return item.wizard;
                };

                Wjs.define({

                    type: 'WizardHeader',

                    internal: {

                        base: ViewHashContainer,

                        initialize: function () {

                            this.addClass('wjs-wizard-header');

                            this.addSection('previousButton',

                                Wjs.new('Button')
                                    .addClass('wjs-button wjs-float-left')
                                    .setText('Previous')
                                    .setAttribute('wjs-role', 'wizard-previous-button')
                                    .disable()
                                    .onClick(function () {

                                        getWizard(this).previous();
                                    })
                            );

                            this.addSection('title',

                                Wjs.new('Label')

                                    .addClass('wjs-wizard-title')
                            );

                            this.addSection('nextButton',

                                Wjs.new('Button')

                                    .addClass('wjs-button wjs-float-right')

                                    .setText('Next')

                                    .setAttribute('wjs-role', 'wizard-next-button')

                                    .onClick(function () {

                                        getWizard(this).next();
                                    })
                            );

                            this.addSection('finishButton',

                                Wjs.new('Button')
                                    .addClass('wjs-button wjs-float-right')
                                    .setText('Finish')
                                    .setAttribute('wjs-role', 'wizard-finish-button')
                                    .hide()
                                    .onClick(function () {

                                        getWizard(this).finish();
                                    })
                            );
                        }
                    },

                    getTitle: function () {

                        return this.getSection('title');
                    }
                });

                Wjs.define({

                    type: 'WizardStep',

                    internal: {

                        base: ViewSingleContainer,

                        initialize: function () {

                            this.addClass('wjs-wizard-step');

                            this.hide();
                        }
                    },

                    setText: function(text) {

                        this.text = text;

                        return this;
                    },

                    setHtml: function(html) {

                        this.html = html;

                        return this;
                    },

                    onActivate: function(fcn) {

                        this.activateHandler = Wjs.chain(this.activateHandler, fcn);

                        return this;
                    },

                    onDeactivate: function (fcn) {

                        this.deactivateHandler = Wjs.chain(this.deactivateHandler, fcn);

                        return this;
                    },

                    enable: function () {

                        this.disabled = false;

                        return this;
                    },

                    disable: function () {

                        this.disabled = true;

                        return this;
                    },

                    isDisabled: function () {

                        return this.disabled;
                    },

                    setSharedData: function (name, data, replace) {

                        getWizard(this).setSharedData(name, data, replace);
                    },

                    getSharedData: function (name) {

                        getWizard(this).getSharedData(name);
                    }
                });
            },

            initialize: function () {
                var me = this;

                me.addClass('wjs-wizard');

                me.addSection('header',

                    Wjs.new('WizardHeader')
                );

                me.addSection('body',

                    Wjs.new('ViewMultipleContainer')
                        .addClass('wjs-wizard-body')
                );

                me.sharedData = {};

                me.activeItem = 0;
            }
        },

        getHeader: function() {

            return this.getSection('header');
        },

        getTitle: function() {

            return this.getHeader().getTitle();
        },

        getBody: function() {

            return this.getSection('body');
        },

        activateHandler: function (step, activationType) {

            // Set the title if provided in the configuration
            if (step.text) {

                this.getTitle().setText(step.text);
            }
            else if (step.html) {

                this.getTitle().setHtml(step.html);
            }

            step.show();

            if (this.stepActivateHandler &&
                this.stepActivateHandler(step, activationType) === false) {

                return; // Do not activate
            }

            if (step.activateHandler &&
                step.activateHandler(activationType) === false) {

                return; // Do not activate
            }

            this.updateButtons();
        },

        deactivateHandler: function (previousStep, activationType) {

            if (this.stepDeactivateHandler &&
                this.stepDeactivateHandler(previousStep, activationType) === false) {

                return false; // Do not deactivate
            }

            if (previousStep.deactivateHandler &&
                previousStep.deactivateHandler(activationType) === false) {

                return false; // Do not deactivate
            }

            previousStep.hide();
        },

        // Adapter method to be used by the Activatable mixin 
        getItem: function (index) {

            return this.getEnabledSteps()[index];
        },

        // Override the Activatable method to return only the enabled steps
        getActiveItem: function() {
            var item = this.activeItem,
                enabledSteps;

            if (Wjs.isNumber(item)) {

                enabledSteps = this.getEnabledSteps();

                if (enabledSteps.length > 0) {

                    return enabledSteps[item];
                }
                else { // No steps to return

                    return null;
                }
            }

            return item;
        },

        onStepActivate: function (fcn) {

            this.stepActivateHandler = Wjs.chain(this.stepActivateHandler, fcn);

            return this;
        },

        onStepDeactivate: function (fcn) {

            this.stepDeactivateHandler = Wjs.chain(this.stepDeactivateHandler, fcn);

            return this;
        },

        onFinish: function (fcn) {

            this.finishHandler = Wjs.chain(this.finishHandler, fcn);

            return this;
        },

        // Adds a step at the specific index
        addStep: function (step, index) {

            this.getBody().addItem(step, index);

            return this;
        },

        addSteps: function (steps, fromIndex) {
            var i,
                length = steps.length;

            fromIndex = fromIndex || 0;

            for (i = 0; i < length; ++i) {

                this.addStep(steps[i], fromIndex + i);
            }

            return this;
        },

        removeStep: function (step) {

        },

        // Returns all the steps, enabled or disabled
        getSteps: function () {

            return this.getBody().getItems();
        },

        getStep: function (index) {

            return this.getSteps()[index];
        },

        // Returns an array of the enabled steps
        getEnabledSteps: function () {
            var i,
                allSteps = this.getSteps(),
                length = allSteps.length,
                enabledSteps = [],
                step;

            for (i = 0; i < length; ++i) {
                step = allSteps[i];

                if (!step.isDisabled()) {

                    enabledSteps.push(step);
                }
            }

            return enabledSteps;
        },

        // Returns the previous enabled step of the parameter one
        getPreviousStep: function (step) {
            var enabledSteps = this.getEnabledSteps(),
                index = enabledSteps.indexOf(step);

            return index == 0 ? null : enabledSteps[index - 1];
        },

        // Returns the next enabled step of the parameter one
        getNextStep: function (step) {
            var enabledSteps = this.getEnabledSteps(),
                length = enabledSteps.length,
                index = enabledSteps.indexOf(step);

            return index + 1 == length ? null : enabledSteps[index + 1];
        },

        updateButtons: function () {
            var enabledSteps = this.getEnabledSteps(),
                length = enabledSteps.length,
                index = enabledSteps.indexOf(this.getActiveItem()),
                previousButton = this.getPreviousButton(),
                nextButton = this.getNextButton(),
                finishButton = this.getFinishButton();

            if (index == 0) { // Disable the previous button for first enabled tab

                previousButton.disable();
            }
            else if (previousButton.isDisabled()) {

                previousButton.enable();
            }

            if (index + 1 == length) {

                nextButton.hide();

                finishButton.show();
            }
            else if (nextButton.isHidden()) {

                nextButton.show();

                finishButton.hide();
            }
        },

        // Advances to the next step
        next: function () {
            var nextStep = this.getNextStep(this.getActiveItem());

            if (nextStep) {

                this.activate(nextStep, 'next');
            }
        },

        // Moves to the previous step
        previous: function () {
            var previousStep = this.getPreviousStep(this.getActiveItem());

            if (previousStep) {

                this.activate(previousStep, 'previous');
            }
        },

        finish: function() {
            var activeStep = this.getActiveItem();

            if (this.stepDeactivateHandler &&
                this.stepDeactivateHandler(activeStep, 'finish') === false) {

                return false; // Do not deactivate
            }

            // Fire the deactivateHandler handle for the currently active step
            if (activeStep &&
                activeStep.deactivateHandler) {

                activeStep.deactivateHandler('finish');
            }

            if (this.finishHandler) {

                this.finishHandler();
            }
        },

        getPreviousButton: function () {

            return this.getHeader().down(function (c) {
                return c instanceof Button && c.getAttribute('wjs-role') == 'wizard-previous-button';
            })[0];
        },

        getNextButton: function () {

            return this.getHeader().down(function (c) {
                return c instanceof Button && c.getAttribute('wjs-role') == 'wizard-next-button';
            })[0];
        },

        getFinishButton: function () {

            return this.getHeader().down(function (c) {
                return c instanceof Button && c.getAttribute('wjs-role') == 'wizard-finish-button';
            })[0];
        },

        setSharedData: function (name, data, replace) {

            this.sharedData[name] = data;
        },

        getSharedData: function (name) {

            return this.sharedData[name];
        }
    });

});
